package a66weding.com.jiehuntong.activity;

import android.animation.ObjectAnimator;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.hardware.Camera;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.OrientationEventListener;
import android.view.Surface;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.TextView;

import java.io.File;
import java.io.IOException;
import java.util.List;

import a66weding.com.jiehuntong.CameraPreview;
import a66weding.com.jiehuntong.R;
import a66weding.com.jiehuntong.common.utils.CUtils;

public class VideoRecorderActivity extends Activity implements View.OnClickListener {
    public static final int H_264 = MediaRecorder.VideoEncoder.H264;
    private ImageButton mShutter;
    private TextView mMinuteText;
    private TextView mSecondText;
    private Camera mCamera;
    private MediaRecorder mRecorder;
    private boolean mIsRecording = false;
    private static final String TAG = "相机";
    private String videoPath;
    private CameraPreview mPreview;
    private MyOrientationDetector orientationDetector;
    private int orientationHint;
    private boolean isTryCatch;
    boolean isError;
    boolean flashing = false;
    private ImageButton imgbtn_flashing;
    boolean currentIsFront = false;
    private FrameLayout preview;
    private View view_placeholder;
    private ImageButton mChangeCamera;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (checkCameraHardware(this)) {
            setContentView(R.layout.activity_video_recorder);
            currentIsFront = false;
            initView();
            if (mCamera==null){
                CUtils.showToastInCenter("相机权限异常！无法获得相机！");
                finish();
            }
        } else {
            CUtils.showToastInCenter("没有找到该设备相机");
            finish();
        }
    }
    //检查是否有相机
    private boolean checkCameraHardware(Context context) {
        if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
            // this device has a camera
            return true;
        } else {
            // no camera on this device
            return false;
        }
    }

    public void changeCamera(View view) throws IOException {
        if (mIsRecording) {
            CUtils.showToastInCenter("录制中无法切换");
        } else {
            int numberOfCameras = Camera.getNumberOfCameras();
            if (numberOfCameras == 2) {
                if (mPreview != null) {
                    mPreview.stopPreview();
                }
                releaseMediaRecorder();
                if (currentIsFront) {
                    releaseCamera();//切换相机一定要释放上次相机，有的机型不释放可能无法切换
                    mCamera = getCameraInstance(false);
                } else {
                    releaseCamera();//切换相机一定要释放上次相机，有的机型不释放可能无法切换
                    mCamera = getCameraInstance(true);
                }
                if (mPreview != null) {
                    mPreview.setmCamera(mCamera);
                    mPreview.rePreview();
                } else {
                    mPreview = new CameraPreview(this, mCamera);
                }
            } else {
                CUtils.showToastInCenter("不支持切换");
            }
        }
    }

    public Camera getCameraInstance(boolean isFront) {
        Camera c = null;
        isError = false;
        try {
            c = Camera.open(findFrontFacingCameraID(isFront));
            currentIsFront = isFront;
            if (c == null) {
                isFront = !isFront;
                c = Camera.open(findFrontFacingCameraID(!isFront));
                currentIsFront = !isFront;
            }
            setCameraDisplayOrientation(findFrontFacingCameraID(currentIsFront), c, true);
        } catch (Exception e) {
            Log.i(TAG, "无权限相机异常或被其他程序占用: " + e);
            isError = true;
            // Camera is not available (in use or does not exist)相机不可用 (在使用或不存在)
            CUtils.showToastInCenter("无权限相机异常或被其他程序占用!");
        }
        if (c != null) {

            // get Camera parameters
            Camera.Parameters params = c.getParameters();
            List<String> focusModes = params.getSupportedFocusModes();
            if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
                Log.i(TAG, "getCameraInstance: 支持视频对焦");
                params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
                c.setParameters(params);
            } else if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
                Log.i(TAG, "getCameraInstance: 支持自动对焦");
                params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
                c.setParameters(params);
            }
        }
        return c;
    }

    public void imgBtnFlashing(View view) {
        if (currentIsFront) {
            CUtils.showToastInCenter("前摄像头不支持打开闪光灯!");
            return;
        }
        if (mIsRecording) {
            CUtils.showToastInCenter("录制中不支持打开或者关闭闪光灯!");
            return;
        }
        if (flashing) {
            flashing = !flashing;
            Camera.Parameters parameter = mCamera.getParameters();
            parameter.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
            mCamera.setParameters(parameter);
            imgbtn_flashing.setImageResource(R.drawable.flashing_on);
        } else {
            flashing = !flashing;
            Camera.Parameters parameter = mCamera.getParameters();
            parameter.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
            mCamera.setParameters(parameter);
            mCamera.setParameters(parameter);
            imgbtn_flashing.setImageResource(R.drawable.flashing_off);
        }
    }

    public void setCameraDisplayOrientation(int cameraId, android.hardware.Camera camera, boolean isPreview) {
        android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();//相机信息
        android.hardware.Camera.getCameraInfo(cameraId, info);//获取相机信息
        Log.i(TAG, "setCameraDisplayOrientation: 默认相机角度：" + info.orientation);
        int rotation = getWindowManager().getDefaultDisplay().getRotation();//获取当前屏幕横竖屏信息
        int degrees = 0;
        switch (rotation) {
            case Surface.ROTATION_0:
                degrees = 0;
                break;
            case Surface.ROTATION_90:
                degrees = 90;
                break;
            case Surface.ROTATION_180:
                degrees = 180;
                break;
            case Surface.ROTATION_270:
                degrees = 270;
                break;
        }
        int result;
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360;
            result = (360 - result) % 360;  // compensate the mirror
        } else {  // back-facing
            result = (info.orientation - degrees + 360) % 360;
        }
        /*---------------------------------------针对mi5splus的预览倒置,录制正常的问题------------------------------*/
        if (isPreview) {
            // 记录本机子相机的旋转角度
            if (Build.MODEL.replaceAll("\\s", "").equals("MI5sPlus") && currentIsFront) {
                if (currentIsFront && result == 90 || result == 270) {
                    if (result == 90) {
                        result += 180;
                    } else {
                        result -= 180;
                    }
                }
            }
        }
        /*--------------------------结束----------------------------------*/
        camera.setDisplayOrientation(result);
    }

    /**
     * @param isFront 是否是前摄像头
     * @return返回摄像头id
     */
    private int findFrontFacingCameraID(boolean isFront) {
        int cameraId = -1;
        // Search for the back facing camera
        int numberOfCameras = Camera.getNumberOfCameras();
        for (int i = 0; i < numberOfCameras; i++) {
            Camera.CameraInfo info = new Camera.CameraInfo();
            Camera.getCameraInfo(i, info);
            if (isFront) {
                if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {//前
                    cameraId = i;
                    return cameraId;
                }
            } else {
                if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {//后
                    cameraId = i;
                    return cameraId;
                }
            }
        }
        return cameraId;
    }

    //初始化控件
    private void initView() {
        imgbtn_flashing = (ImageButton) findViewById(R.id.imgbtn_flashing);
        mMinuteText = (TextView) findViewById(R.id.timestamp_minute_text);
        mSecondText = (TextView) findViewById(R.id.timestamp_second_text);
        mShutter = (ImageButton) findViewById(R.id.record_shutter);
        mChangeCamera = (ImageButton) findViewById(R.id.imgbtn_change_camera);

        mShutter.setOnClickListener(this);
        mCamera = getCameraInstance(false);
    }

    //页面失去焦点
    @Override
    protected void onPause() {
        super.onPause();
        releaseMediaRecorder();       // if you are using MediaRecorder, release it first    如果您使用的是媒体录制器，首先释放它
        releaseCamera();              // release the camera immediately on pause event     释放的照相机立即暂停事件
        orientationDetector.disable();//关闭方向传感
    }

    @Override
    public void onClick(View v) {
        if (mIsRecording) {
            stopRecording(true);//停止按钮按下后停止录像并返回录像结果
            imgbtn_flashing.setVisibility(View.VISIBLE);
        } else {
            boolean b = prepareVideoRecorder(true);
            if (b) {
                orientationDetector.disable();
                startRecording();
                // imgbtn_flashing.setVisibility(View.GONE);
            } else {
                // imgbtn_flashing.setVisibility(View.VISIBLE);
                CUtils.showToastInCenter("录像机准备失败！");
                releaseMediaRecorder();//录像机准备失败
            }
        }
    }

    /**
     * 初始化多媒体录制工具
     *
     * @param isSetAttribute 是否设置一些属性，某些手机不支持
     * @return 返回的是否准备完毕
     */
    private boolean prepareVideoRecorder(boolean isSetAttribute) {
        if (mRecorder == null) {
            mRecorder = new MediaRecorder();
        }
        mRecorder.reset();
    /*-----------------------------Mi5sPlus前摄像头预览问题开始-----------------------------------*/
        if (Build.MODEL.replaceAll("\\s", "").equals("MI5sPlus") && currentIsFront) {
            if (mCamera == null) {
                mCamera = getCameraInstance(currentIsFront);
                if (mPreview == null) {
                    mPreview = new CameraPreview(this, mCamera);
                } else {
                    mPreview.stopPreview();
                    mPreview.setmCamera(mCamera);
                    mPreview.rePreview();
                }
            }
            mCamera.stopPreview();
            setCameraDisplayOrientation(findFrontFacingCameraID(currentIsFront), mCamera, false);
            mCamera.startPreview();
        }
  /*-----------------------------------Mi5sPlus前摄像头预览问题结束---------------------------*/
        mCamera.unlock();
        mRecorder.setCamera(mCamera);
        Log.i(TAG, "prepareVideoRecorder: 是否是前摄像头：" + currentIsFront + "改变前当前角度：" + orientationHint);
        int tempOrientation = orientationHint;
        if (currentIsFront && orientationHint == 90 || orientationHint == 270) {
            if (orientationHint == 90) {
                tempOrientation += 180;
            } else {
                tempOrientation -= 180;
            }
        }
        Log.i(TAG, "prepareVideoRecorder: 是否是前摄像头：" + currentIsFront + "改变后角度：" + orientationHint);
        mRecorder.setOrientationHint(tempOrientation);
        mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); // 设置从录像机
        mRecorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT); // 设置从摄像头采集图像
        //格式
        mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);  // 设置视频的输出格式 为MP4
        mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); // 设置音频的编码格式其他格式有的pc不支持
        mRecorder.setVideoEncoder(H_264); // 设置视频的编码格式
        mRecorder.setMaxDuration(1000 * 60 * 10);//最大10分钟

        if (isSetAttribute) {//小米5splus不支持设置自定义大小等这些东西
            //设置视频比特率以及帧率
            CamcorderProfile mProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_480P);
            mRecorder.setVideoSize(mProfile.videoFrameWidth, mProfile.videoFrameHeight);  // 设置视频大小
            mRecorder.setAudioEncodingBitRate(mProfile.audioBitRate / 100);
            if (mProfile.videoBitRate > 1 * 1024 * 1024) {
                mRecorder.setVideoEncodingBitRate(1 * 1024 * 1024 / 2);
            } else {
                mRecorder.setVideoEncodingBitRate(mProfile.videoBitRate / 2);
            }
            mRecorder.setVideoFrameRate(mProfile.videoFrameRate / 3);// 设置帧率
        }
        //设置视频存储路径
        File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) + File.separator + "66weddingVideo");
        if (!file.exists()) {
            //多级文件夹的创建
            file.mkdirs();
        }
        videoPath = file.getAbsolutePath() + File.separator + "VID_" + System.currentTimeMillis() + "66wedding.mp4";
        mRecorder.setOutputFile(videoPath);
        try {
            mRecorder.prepare();
        } catch (IllegalStateException e) {
            //删除文件
            if (new File(videoPath).exists()) {
                new File(videoPath).delete();
            }
            Log.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage());
            releaseMediaRecorder();//准备异常
            return false;
        } catch (IOException e) {
            //删除文件
            if (new File(videoPath).exists()) {
                new File(videoPath).delete();
            }
            Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage());
            releaseMediaRecorder();//准备IO异常
            return false;
        }
        return true;
    }

    /**
     * 释放多媒体录制工具
     */
    private void releaseMediaRecorder() {
        if (mRecorder != null) {
            mRecorder.reset();   // clear recorder configuration清除记录的配置
            mRecorder.release(); // release the recorder object释放记录器对象
            mRecorder = null;
            mCamera.lock();  // lock camera for later use
        }
    }

    /**
     * 释放相机
     */
    private void releaseCamera() {
        if (mCamera != null) {
            mPreview.removeCallback();//移除相机预览回调
            mCamera.stopPreview();//停止预览
            mCamera.release();// release the camera for other applications释放照相机为其他应用程序
            mCamera = null;//制空相机对象
        }
    }

    //录制
    private void startRecording() {
        if (mIsRecording) {
            CUtils.showToastInCenter("正在录制!");
        } else {
            if (mRecorder != null) {
                try {
                    mRecorder.start();//开始拍摄
                    mShutter.setImageDrawable(getResources().getDrawable(R.drawable.icon_stop));//更改图标
                    mIsRecording = true;//更改录制标志为正在录制
                    //开始录像后，每隔1s去更新录像的时间戳
                    mHandler.postDelayed(mTimestampRunnable, 1000);
                } catch (Exception e) {
                    mIsRecording = false;//如果意外结束是否录制的标志设置为未录制
                    mShutter.setImageDrawable(getResources().getDrawable(R.drawable.icon_continue));//更改图标
                    //停止录像时间的计时器
                    mHandler.removeCallbacks(mTimestampRunnable);
                    //将录像时间还原
                    mMinuteText.setText("10");
                    mSecondText.setText("00");
                    if (isTryCatch) {
                        CUtils.showToastInCenter("录像机出错!无法录制!");
                        finish();
                    } else {
                        isTryCatch = true;
                        releaseMediaRecorder();//录像机开始异常
                        boolean b = prepareVideoRecorder(false);
                        if (b) {
                            startRecording();
                        } else {
                            CUtils.showToastInCenter("录像机准备失败");
                            releaseMediaRecorder();//录像机准备失败
                        }
                    }

                }
            }
        }
    }

    /***
     * 停止录制并销毁录制页面
     * @param isFinish 是否返回录制结果
     */
    private void stopRecording(boolean isFinish) {
        mRecorder.setOnErrorListener(null);
        mRecorder.setOnInfoListener(null);
        mRecorder.setPreviewDisplay(null);
        mRecorder.stop();
        releaseMediaRecorder();//停止异常
        mIsRecording = false;
        //更改按钮图标
        mShutter.setImageDrawable(getResources().getDrawable(R.drawable.icon_continue));
        //更改按录制状态
        mIsRecording = false;
        //停止录像时间的计时器
        mHandler.removeCallbacks(mTimestampRunnable);
        //将录像时间还原
        mMinuteText.setText("10");
        mSecondText.setText("00");
        if (isFinish) {
            //设置返回本路径结果然后关闭
            Intent intent = new Intent();
            intent.putExtra("videoPath", videoPath);
            this.setResult(969, intent);
            //关闭当前页面
            finish();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        isError = false;//初始化错误
        mRecorder = new MediaRecorder();//初始化录像机
        mPreview = new CameraPreview(this, mCamera);//预览的view
        preview = (FrameLayout) findViewById(R.id.camera_preview);//预览的父控件
        preview.addView(mPreview);//添加进来
        mIsRecording = false;//初始化录制状态
        mShutter.setImageDrawable(getResources().getDrawable(R.drawable.icon_continue));//初始化录制图标
        //停止录像时间的计时器
        mHandler.removeCallbacks(mTimestampRunnable);//倒计时工具初始化
        //将录像时间还原
        mMinuteText.setText("10");//倒计时时间初始化
        mSecondText.setText("00");//倒计时时间初始化
        orientationDetector = new MyOrientationDetector(this);//添加方向传感器
        if (isError) {//如果发生错误直接关闭页面
            finish();
        }
        orientationDetector.enable();
    }

    private Runnable mTimestampRunnable = new Runnable() {
        @Override
        public void run() {
            updateTimestamp();
            mHandler.postDelayed(this, 1000);
        }
    };
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
        }
    };

    /**
     * 显示录制时间的工具倒计时
     */
    private void updateTimestamp() {
        int second = Integer.parseInt(mSecondText.getText().toString());
        int minute = Integer.parseInt(mMinuteText.getText().toString());
        if (second == 0 && minute == 0) {
            stopRecording(true);//时间到了，就停止返回录像结果
        } else if (second == 0) {//秒数等于0则减一分钟
            if (minute > 0) {
                minute--;
            }
            if (minute > 9) {//如果分钟数大于9直接显示
                mMinuteText.setText(String.valueOf(minute));
            } else {//小于则拼个0
                mMinuteText.setText("0" + minute);
            }
            mSecondText.setText(String.valueOf("59"));//把描述置为59
        } else if (second > 0) {//秒大于零-1秒
            second--;
            if (second > 9) {
                mSecondText.setText(String.valueOf(second));
            } else {
                mSecondText.setText("0" + second);
            }
        }
    }

    /**
     * 方向传感器
     */
    public class MyOrientationDetector extends OrientationEventListener {

        public MyOrientationDetector(Context context) {
            super(context);
        }

        @Override
        public void onOrientationChanged(int orientation) {
            if (orientation == OrientationEventListener.ORIENTATION_UNKNOWN) {
                orientation = 0; //手机平放时，检测不到有效的角度
            }
            //只检测是否有四个角度的改变
            if (orientation >= 70 && orientation < 110) { //90度
                orientation = 90 + 90;
            } else if (orientation >= 160 && orientation < 200) { //180度
                orientation = 180 + 90;
            } else if (orientation >= 250 && orientation < 290) { //270度
                orientation = 270 - 270;
            } else {
                orientation = 0 + 90;
            }
            orientationHint = orientation;
        }
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        initView();
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == event.KEYCODE_HOME) {
            if (mIsRecording) {
                stopRecording(false); //如果录制中就停止并不返回录制结果
            }
            releaseCamera();//如果是back键就释放相机
        }
        return super.onKeyDown(keyCode, event);
    }
}